<script setup lang="ts">
import type { FormInstance } from 'ant-design-vue';
import type { Rule } from 'ant-design-vue/es/form/interface';
import type { SegmentedValue } from 'ant-design-vue/es/segmented/src/segmented';
import type { SelectValue } from 'ant-design-vue/es/select';

import type { DictOption } from '#/store/dict';

import { computed, ref } from 'vue';

import { useVbenDrawer } from '@vben/common-ui';
import { DictEnum } from '@vben/constants';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';

import {
  DeleteOutlined,
  MinusCircleOutlined,
  PlusCircleOutlined,
} from '@ant-design/icons-vue';
import {
  Form,
  FormItem,
  Input,
  Segmented,
  Select,
  SelectOption,
  Switch,
  Textarea,
} from 'ant-design-vue';

import {
  addAlarmConfig,
  AlarmConfigDetail,
  deviceSelect,
  productSelect,
  propertySelect,
  thingModelSelect,
  updateAlarmConfig,
} from '#/api/iot/alarm/config';
import { getDictOptions } from '#/utils/dict';

const emit = defineEmits(['success', 'reload']);
const isUpdate = ref(false);
const productOption = ref<{ id: number; productName: string }[]>([]); // 产品下拉
const deviceOption = ref<{ deviceName: string; id: number }[]>([]); // 设备下拉
const modelOption = ref<{ blockIdentifier: string; id: number }[]>([]); // 模型下拉
const propertyOption = ref<{ id: number; identifier: string }[]>([]); // 属性下拉
const symbolOption = ref<DictOption[]>([]); // 符号字典
const levelOption = ref<DictOption[]>([]); // 等级字典
const conditionOption = ref<DictOption[]>([]); // 条件字典
const tabsValue = ref(1); // 监听器 | 输出

const title = computed(() => {
  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
});
const formRef = ref<FormInstance>();

interface FormState {
  alarmName: string;
  productId: number | undefined;
  deviceIds: string[];
  alarmDesc: string;
  level: number | undefined;
  enabled: number;
  alarmListener: any;
  alarmActions: any;
}

const labelCol = { span: 3 };
const wrapperCol = { span: 20 };
const formState = ref<FormState>({
  alarmName: '',
  productId: undefined,
  deviceIds: [],
  alarmDesc: '',
  level: undefined,
  enabled: 1,
  alarmListener: {
    conditions: [
      {
        type: undefined,
        value: undefined,
        parameters: [
          {
            blockId: undefined,
            blockIdentifier: undefined,
            itemId: undefined,
            identifier: undefined,
            dataType: undefined,
            comparator: undefined,
            value: undefined,
          },
        ],
      },
    ],
  },
  // 输出类型（1：短信邮箱通知；2：HTTP推送；3：企微机器人）
  alarmActions: [],
});
const rules: Record<string, Rule[]> = {
  alarmName: [
    {
      required: true,
      message: '请输入名称',
      trigger: 'blur',
    },
  ],
  productId: [
    {
      required: true,
      message: '请选择产品',
      trigger: 'change',
    },
  ],
  deviceIds: [
    {
      required: true,
      message: '请选择设备',
      trigger: 'change',
    },
  ],
  alarmDesc: [
    {
      required: false,
      message: '请输入描述',
      trigger: 'blur',
    },
  ],
  level: [
    {
      required: true,
      message: '请选择级别',
      trigger: 'change',
    },
  ],
  enabled: [
    {
      required: true,
      message: '请选择是否启用',
      trigger: 'change',
    },
  ],
};

// 获取产品下拉
async function getProductSelect() {
  const res = await productSelect();
  productOption.value = res;
}
// 产品change事件
async function handleProductChange(id: SelectValue) {
  await getDeviceSelect(id as number);
  await getThingModelSelect(id as number);
}
// 获取设备下拉
async function getDeviceSelect(id: number) {
  formState.value.deviceIds = [];
  deviceOption.value = [];
  const res = await deviceSelect(id);
  deviceOption.value = res;
}

// 获取物模型功能模块下拉数据源
async function getThingModelSelect(id: number) {
  const res = await thingModelSelect(id);
  modelOption.value = res;
}

// 物模型联动属性
async function handleModelChange(option: any, index1: number, index2: number) {
  const modelData =
    formState.value.alarmListener.conditions[index1].parameters[index2];
  modelData.blockldentifier = option.blockIdentifier;
  modelData.blockId = option.id;
  modelData.itemId = undefined;
  if (isUpdate.value) {
    modelData.property = await propertySelect(option.id as number);
  } else {
    await getPropertySelect(option.id as number);
  }
}

// 属性change事件
async function handlePropertyChange(
  option: any,
  index1: number,
  index2: number,
) {
  const propertyData =
    formState.value.alarmListener.conditions[index1].parameters[index2];

  propertyData.identifier = option.identifier;
  propertyData.dataType = option.dataType;
  propertyData.comparator = undefined;
  propertyData.comparators = await getComparator(option.dataType);
}

// 获取属性下拉数据源
async function getPropertySelect(id: number) {
  const res = await propertySelect(id);
  propertyOption.value = res.map(
    (option: { identifier: string; name: string }) => ({
      ...option,
      customLabel: `${option.name}${option.identifier}`, // 你可以在这里更改label
    }),
  );
}

// 符号| 条件 | 等级 字典
async function dictData() {
  levelOption.value = await getDictOptions(DictEnum.IOT_ALARM_LEVEL_TYPE);
  conditionOption.value = await getDictOptions(
    DictEnum.IOT_ALARM_CONDITION_TYPE,
  );
  symbolOption.value = await getDictOptions(DictEnum.IOT_SYMBOL_TYPE);
}

dictData();

// 切换监听器 | 输出
function onChangeTabsType(value: SegmentedValue) {
  tabsValue.value = value as number;
}

// 新增监听器|输出上报条件  tabsValue1是监听器 2是输出
function addSight() {
  if (tabsValue.value === 1) {
    formState.value.alarmListener.conditions.push({
      type: undefined,
      value: undefined,
      parameters: [
        {
          blockId: undefined,
          blockIdentifier: undefined,
          itemId: undefined,
          identifier: undefined,
          dataType: undefined,
          comparator: undefined,
          value: undefined,
        },
      ],
    });
  } else {
    formState.value.alarmActions.push({
      actionType: undefined,
      httpUrl: undefined,
      wxWebhookUrl: undefined,
    });
  }
}
// 删除监听器|输出上报条件
function removeSight(index: number) {
  if (tabsValue.value === 1) {
    formState.value.alarmListener.conditions.splice(index, 1);
  } else {
    formState.value.alarmActions.splice(index, 1);
  }
}
// 新增属性上报条件的配置
function addSightItem(conditionIndex: number) {
  formState.value.alarmListener.conditions[conditionIndex].parameters.push({
    blockId: undefined,
    blockIdentifier: undefined,
    itemId: undefined,
    identifier: undefined,
    dataType: undefined,
    comparator: undefined,
    value: undefined,
  });
}
// 删除属性上报条件的配置
function removeSightItem(conditionIndex: number, parametersIndex: number) {
  formState.value.alarmListener.conditions[conditionIndex].parameters.splice(
    parametersIndex,
    1,
  );
}

const [BasicDrawer, drawerApi] = useVbenDrawer({
  onClosed: handleClosed,
  onConfirm: handleConfirm,
  onOpenChange: async (isOpen) => {
    if (!isOpen) {
      return null;
    }
    const { id } = drawerApi.getData() as { id?: number };
    isUpdate.value = !!id;
    await getProductSelect();
    if (isUpdate.value && id) {
      drawerApi.drawerLoading(true);
      const record = await AlarmConfigDetail(id);
      await getDeviceSelect(record.productId as number);
      await getThingModelSelect(record.productId as number);
      // 删除输出详情中的id字段
      if (record.alarmActions.length > 0) {
        record.alarmActions = record.alarmActions.map((item: { id: any }) => {
          delete item.id;
          return item; // 返回修改后的对象
        });
      }
      // 联动属性
      await Promise.all(
        record.alarmListener.conditions.map(
          async (element: { parameters: any[]; type: string }) => {
            if (element.type === 'deviceStatus') {
              return; // 如果 type 为 'deviceStatus'，跳过该项，不执行下面的 for 循环
            }
            for (const elementChild of element.parameters) {
              const propertyList = await propertySelect(elementChild.blockId);
              elementChild.property = propertyList.map(
                (option: { identifier: string; name: string }) => ({
                  ...option,
                  customLabel: `${option.name}${option.identifier}`, // 你可以在这里更改label
                }),
              );
              elementChild.comparators = getComparator(elementChild.dataType);
            }
          },
        ),
      );
      formState.value = record;
      console.log(formState.value, 'formState.value ');
    }
    drawerApi.drawerLoading(false);
  },
});
// 根据dataType类型获取对应的数组
function getComparator(dataType: string) {
  const comparator = ref<DictOption[]>([]);
  switch (dataType) {
    case 'bool': {
      // bool 等于 不等于
      comparator.value = symbolOption.value.filter((item) =>
        ['5', '6'].includes(item.value as string),
      );
      break;
    }
    case 'float':
    case 'int32': {
      // 数值类型：有大于 小于 等于
      comparator.value = symbolOption.value.filter((item) =>
        ['1', '2', '3', '4', '5', '6'].includes(item.value as string),
      );

      break;
    }
    case 'text': {
      // 字符串类型：等于 不等于 包含 不包含
      comparator.value = symbolOption.value.filter((item) =>
        ['5', '6', ' 7', '8'].includes(item.value as string),
      );
      break;
    }
    default: {
      comparator.value = symbolOption.value; // 或者设置为一个空数组 []
      break;
    }
  }

  return comparator.value;
}

function handleConfirm() {
  try {
    drawerApi.lock(true);
    formRef.value
      ?.validate()
      .then(async () => {
        drawerApi.drawerLoading(true);
        const data = cloneDeep(formState.value);
        await (isUpdate.value ? updateAlarmConfig(data) : addAlarmConfig(data));
        drawerApi.drawerLoading(false);
        emit('reload');
        drawerApi.close();
      })
      .catch((error: any) => {
        console.log('error', error);
        drawerApi.drawerLoading(false);
      });
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.lock(false);
  }
}

async function handleClosed() {
  formRef.value?.resetFields();
  resetForm();
  drawerApi.close();
}

function resetForm() {
  formState.value.alarmListener.conditions = [
    {
      type: undefined,
      value: undefined,
      parameters: [
        {
          blockId: undefined,
          blockIdentifier: undefined,
          itemId: undefined,
          identifier: undefined,
          dataType: undefined,
          comparator: undefined,
          value: undefined,
        },
      ],
    },
  ];
  formState.value.alarmActions = [];
  productOption.value = [];
  deviceOption.value = [];
  modelOption.value = [];
  propertyOption.value = [];
  tabsValue.value = 1;
}
</script>

<template>
  <BasicDrawer :title="title" class="w-[60%]">
    <Form
      ref="formRef"
      :model="formState"
      :rules="rules"
      :label-col="labelCol"
      :wrapper-col="wrapperCol"
      style="width: 100%"
    >
      <FormItem label="名称" name="alarmName">
        <Input v-model:value="formState.alarmName" placeholder="请输入名称" />
      </FormItem>
      <FormItem label="产品" name="productId">
        <Select
          @change="handleProductChange"
          v-model:value="formState.productId"
          placeholder="请选择产品"
          :options="productOption"
          :field-names="{ label: 'productName', value: 'id' }"
        />
      </FormItem>
      <FormItem label="设备" name="deviceIds">
        <Select
          mode="multiple"
          v-model:value="formState.deviceIds"
          placeholder="请选择设备"
          :options="deviceOption"
          :field-names="{ label: 'deviceName', value: 'id' }"
        />
      </FormItem>
      <FormItem label="描述" name="alarmDesc">
        <Textarea
          v-model:value="formState.alarmDesc"
          placeholder="请输入描述"
        />
      </FormItem>
      <FormItem label="告警级别" name="level">
        <Select
          v-model:value="formState.level"
          :options="levelOption"
          placeholder="请选择告警级别"
        />
      </FormItem>
      <FormItem label="是否启用" name="enabled">
        <Switch
          v-model:checked="formState.enabled"
          :checked-value="1"
          :un-checked-value="0"
        />
      </FormItem>
      <FormItem>
        <Segmented
          class="ml-5"
          v-model:value="tabsValue"
          :options="[
            { label: '监听器', value: 1 },
            { label: '输出', value: 2 },
          ]"
          @change="onChangeTabsType"
        />
      </FormItem>
      <div
        v-show="tabsValue === 1"
        v-for="(sight, index) in formState.alarmListener?.conditions"
        :key="index"
        class="condition"
      >
        <div class="catalogue">
          <FormItem
            :name="['alarmListener', 'conditions', index, 'type']"
            :rules="[{ required: true, message: '请选择条件' }]"
          >
            <Select
              v-model:value="sight.type"
              placeholder="请选择条件"
              :options="conditionOption"
            />
          </FormItem>
        </div>
        <!-- 属性上报 -->
        <div class="napeBxo" v-if="sight.type !== 'deviceStatus'">
          <div
            class="nape"
            v-for="(sights, indexs) in sight.parameters"
            :key="indexs"
          >
            <FormItem
              :name="[
                'alarmListener',
                'conditions',
                index,
                'parameters',
                indexs,
                'blockId',
              ]"
              :rules="{
                required: true,
                message: '请选择物模型',
              }"
            >
              <Select
                v-model:value="sights.blockId"
                placeholder="请选择物模型"
                style="width: 140px"
                :options="modelOption"
                :field-names="{
                  value: 'id',
                  label: 'blockIdentifier',
                  options: 'modelOption',
                }"
                @change="
                  (_, option) => handleModelChange(option, index, indexs)
                "
              />
            </FormItem>

            <FormItem
              :name="[
                'alarmListener',
                'conditions',
                index,
                'parameters',
                indexs,
                'itemId',
              ]"
              :rules="{
                required: true,
                message: '请选择属性',
              }"
            >
              <Select
                v-model:value="sights.itemId"
                placeholder="请选择属性"
                style="width: 140px"
                :options="isUpdate ? sights.property : propertyOption"
                :field-names="{
                  value: 'id',
                  label: 'customLabel',
                  options: 'propertyOption',
                }"
                @change="
                  (_, option) => handlePropertyChange(option, index, indexs)
                "
              />
            </FormItem>
            <FormItem
              :name="[
                'alarmListener',
                'conditions',
                index,
                'parameters',
                indexs,
                'comparator',
              ]"
              :rules="{
                required: true,
                message: '请选择符号',
              }"
            >
              <Select
                v-model:value="sights.comparator"
                placeholder="请选择符号"
                style="width: 140px"
              >
                <SelectOption
                  v-for="item in sights.itemId
                    ? sights.comparators
                    : symbolOption"
                  :key="item.value"
                  :value="item.value"
                >
                  {{ item.dictLabel }}
                </SelectOption>
              </Select>
            </FormItem>
            <FormItem
              class="SightItem"
              :name="[
                'alarmListener',
                'conditions',
                index,
                'parameters',
                indexs,
                'value',
              ]"
              :rules="{
                required: true,
                message: '请输入',
              }"
            >
              <Input v-model:value="sights.value" placeholder="请输入" />

              <PlusCircleOutlined
                v-if="indexs === 0"
                class="addSightItem"
                @click="addSightItem(index)"
              />
              <MinusCircleOutlined
                v-else
                class="removeSightItem"
                @click="removeSightItem(index, indexs)"
              />
            </FormItem>
          </div>
        </div>
        <!-- 设备上下线 -->
        <div class="napeBxo" v-if="sight.type === 'deviceStatus'">
          <FormItem
            :name="['alarmListener', 'conditions', index, 'value']"
            :rules="[{ required: true, message: '请选择条件' }]"
          >
            <Select
              v-model:value="sight.value"
              placeholder="请选择在线状态"
              :options="[
                { label: '上线', value: 'online' },
                { label: '下线', value: 'offline' },
              ]"
            />
          </FormItem>
        </div>
        <div class="action">
          <DeleteOutlined
            v-if="index !== 0"
            class="removeSight"
            @click="removeSight(index)"
            style="font-size: 18px; color: red"
          />
        </div>
      </div>

      <div
        v-show="tabsValue === 2"
        v-for="(item, index) in formState.alarmActions"
        :key="index"
        class="condition"
      >
        <div class="catalogue">
          <FormItem
            :name="['alarmActions', index, 'actionType']"
            :rules="[{ required: true, message: '请选择类型' }]"
          >
            <Select
              v-model:value="item.actionType"
              placeholder="请选择条件"
              :options="[
                {
                  label: 'http推送',
                  value: 2,
                },
                {
                  label: '企微机器人',
                  value: 3,
                },
              ]"
            />
          </FormItem>
        </div>
        <div class="napeBxo">
          <FormItem
            v-if="item.actionType === 2 || item.actionType === undefined"
            class="SightItem"
            :name="['alarmActions', index, 'httpUrl']"
            :rules="{
              required: true,
              message: '请输入HTTP推送地址',
            }"
          >
            <Input
              v-model:value="item.httpUrl"
              placeholder="请输入HTTP推送地址"
            />
          </FormItem>
          <FormItem
            v-if="item.actionType === 3"
            class="SightItem"
            :name="['alarmActions', index, 'wxWebhookUrl']"
            :rules="{
              required: true,
              message: '请输入企业微信机器人 Webhook 地址',
            }"
          >
            <Input
              v-model:value="item.wxWebhookUrl"
              placeholder="请输入企业微信机器人 Webhook 地址"
            />
          </FormItem>
        </div>
        <div class="action">
          <DeleteOutlined
            class="removeSight"
            @click="removeSight(index)"
            style="font-size: 18px; color: red"
          />
        </div>
      </div>

      <a-button type="dashed" block @click="addSight">
        {{ tabsValue === 1 ? '新增条件' : '新增输出' }}
      </a-button>
    </Form>
  </BasicDrawer>
</template>
<style lang="scss" scoped>
.condition {
  width: 100%;

  display: flex;
  align-items: center;
  padding: 10px 0 10px 19px;
  position: relative;

  margin-bottom: 10px;
  background-color: aliceblue;
  border-radius: 10px;
  .catalogue {
    width: 20%;
    .ant-form-item {
      margin-bottom: 0;
    }
  }

  .napeBxo {
    width: 70%;

    .ant-form-item {
      margin-bottom: 0;
    }
    .nape {
      display: flex;
      flex: 4;
      justify-content: space-between;
      margin-bottom: 10px;
      &:first-child {
        margin-bottom: 0;
      }
      .SightItem {
        position: relative;
        .addSightItem {
          position: absolute;
          right: -20px;
          top: 10px;
        }
        .removeSightItem {
          position: absolute;
          right: -20px;
          top: 10px;
        }
      }
    }
  }
  .action {
    width: 10%;
    .removeSight {
      position: absolute;
      top: 17px;
      right: 15px;
    }
  }
}
</style>
